home *** CD-ROM | disk | FTP | other *** search
/ Speccy ClassiX 1998 / Speccy ClassiX 98.iso / amiga_system / the_aminet / dev / gcc / ixemulsrc.lha / ixemul-41.4 / stdlib / exec.c < prev    next >
C/C++ Source or Header  |  1995-05-28  |  7KB  |  278 lines

  1. /*-
  2.  * Copyright (c) 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #if defined(LIBC_SCCS) && !defined(lint)
  35. static char sccsid[] = "@(#)exec.c    5.9 (Berkeley) 6/17/91";
  36. #endif /* LIBC_SCCS and not lint */
  37.  
  38. #define KERNEL
  39. #include "ixemul.h"
  40. #include "kprintf.h"
  41.  
  42. #include <errno.h>
  43. #include <unistd.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #include <paths.h>
  47.  
  48. #ifdef __STDC__
  49. #include <stdarg.h>
  50. #else
  51. #include <varargs.h>
  52. #endif
  53.  
  54. #define environ (*u.u_environ)
  55.  
  56. static char **
  57. buildargv(ap, arg, envpp)
  58.     va_list ap;
  59.     const char *arg;
  60.     char ***envpp;
  61. {
  62.     register size_t max, off;
  63.     register char **argv = NULL;
  64.  
  65.     for (off = max = 0;; ++off) {
  66.         if (off >= max) {
  67.             max += 50;    /* Starts out at 0. */
  68.             max *= 2;    /* Ramp up fast. */
  69.             if (!(argv = realloc(argv, max * sizeof(char *))))
  70.                 return(NULL);
  71.             if (off == 0) {
  72.                 argv[0] = (char *)arg;
  73.                 off = 1;
  74.             }
  75.         }
  76.         if (!(argv[off] = va_arg(ap, char *)))
  77.             break;
  78.     }
  79.     /* Get environment pointer if user supposed to provide one. */
  80.     if (envpp)
  81.         *envpp = va_arg(ap, char **);
  82.     return(argv);
  83. }
  84.  
  85. int
  86. #if __STDC__
  87. execl(const char *name, const char *arg, ...)
  88. #else
  89. execl(name, arg, va_alist)
  90.     const char *name;
  91.     const char *arg;
  92.     va_dcl
  93. #endif
  94. {
  95.     va_list ap;
  96.     int sverrno;
  97.     char **argv;
  98.  
  99. #if __STDC__
  100.     va_start(ap, arg);
  101. #else
  102.     va_start(ap);
  103. #endif
  104.     if (argv = buildargv(ap, arg, (char ***)NULL))
  105.         (void)execve(name, argv, environ);
  106.     va_end(ap);
  107.     sverrno = errno;
  108.     free(argv);
  109.     errno = sverrno;
  110.     KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  111.     return(-1);
  112. }
  113.  
  114. int
  115. #if __STDC__
  116. execle(const char *name, const char *arg, ...)
  117. #else
  118. execle(name, arg, va_alist)
  119.     const char *name;
  120.     const char *arg;
  121.     va_dcl
  122. #endif
  123. {
  124.     va_list ap;
  125.     int sverrno;
  126.     char **argv, **envp;
  127.  
  128. #if __STDC__
  129.     va_start(ap, arg);
  130. #else
  131.     va_start(ap);
  132. #endif
  133.     if (argv = buildargv(ap, arg, &envp))
  134.         (void)execve(name, argv, envp);
  135.     va_end(ap);
  136.     sverrno = errno;
  137.     free(argv);
  138.     errno = sverrno;
  139.     KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  140.     return(-1);
  141. }
  142.  
  143. int
  144. #if __STDC__
  145. execlp(const char *name, const char *arg, ...)
  146. #else
  147. execlp(name, arg, va_alist)
  148.     const char *name;
  149.     const char *arg;
  150.     va_dcl
  151. #endif
  152. {
  153.     va_list ap;
  154.     int sverrno;
  155.     char **argv;
  156.  
  157. #if __STDC__
  158.     va_start(ap, arg);
  159. #else
  160.     va_start(ap);
  161. #endif
  162.     if (argv = buildargv(ap, arg, (char ***)NULL))
  163.         (void)execvp(name, argv);
  164.     va_end(ap);
  165.     sverrno = errno;
  166.     free(argv);
  167.     errno = sverrno;
  168.     KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  169.     return(-1);
  170. }
  171.  
  172. int
  173. execv(name, argv)
  174.     const char *name;
  175.     char * const *argv;
  176. {
  177.     (void)execve(name, argv, environ);
  178.     return(-1);
  179. }
  180.  
  181. int
  182. execvp(name, argv)
  183.     const char *name;
  184.     char * const *argv;
  185. {
  186.     register int lp, ln;
  187.     register char *p;
  188.     int eacces, etxtbsy;
  189.     char *bp, *cur, *path, buf[MAXPATHLEN];
  190.  
  191.     /* If it's an absolute or relative path name, it's easy. */
  192.     if (index(name, '/') || index (name, ':')) {
  193.         bp = (char *)name;
  194.         cur = path = NULL;
  195.         goto retry;
  196.     }
  197.     bp = buf;
  198.  
  199.     /* first try to call execve() without path lookup. execve() walks
  200.        a (possibly provided) CLI PATH, and also supports resident
  201.        programs. If this fails, we can still try to find the program
  202.        along the $PATH */
  203.     execv (name, argv);
  204.     /* if we get here, the execv() failed. So start magic ;-)) */
  205.  
  206.     /* Get the path we're searching. */
  207.     if (!(path = getenv("PATH")))
  208.         path = _PATH_DEFPATH;
  209.     cur = path = strdup(path);
  210.  
  211.     eacces = etxtbsy = 0;
  212.     while (p = strsep(&cur, ",:")) {
  213.         /*
  214.          * It's a SHELL path -- double, leading and trailing colons
  215.          * mean the current directory.
  216.          */
  217.         if (!*p) {
  218.             p = ".";
  219.             lp = 1;
  220.         } else
  221.             lp = strlen(p);
  222.         ln = strlen(name);
  223.  
  224.         /*
  225.          * If the path is too long complain.  This is a possible
  226.          * security issue; given a way to make the path too long
  227.          * the user may execute the wrong program.
  228.          */
  229.         if (lp + ln + 2 > sizeof(buf)) {
  230.             (void)write(STDERR_FILENO, "execvp: ", 8);
  231.             (void)write(STDERR_FILENO, p, lp);
  232.             (void)write(STDERR_FILENO, ": path too long\n", 16);
  233.             continue;
  234.         }
  235.         bcopy(p, buf, lp);
  236.         buf[lp] = '/';
  237.         bcopy(name, buf + lp + 1, ln);
  238.         buf[lp + ln + 1] = '\0';
  239.  
  240. retry:        (void)execve(bp, argv, environ);
  241.         switch(errno) {
  242.         case EACCES:
  243.             eacces = 1;
  244.             break;
  245.         case ENOENT:
  246.             break;
  247.         case ENOEXEC: {
  248.             register size_t cnt;
  249.             register char **ap;
  250.  
  251.             for (cnt = 0, ap = (char **)argv; *ap; ++ap, ++cnt);
  252.             if (ap = malloc((cnt + 2) * sizeof(char *))) {
  253.                 bcopy(argv + 1, ap + 2, cnt * sizeof(char *));
  254.                 ap[0] = "sh";
  255.                 ap[1] = bp;
  256.                 (void)execve(_PATH_BSHELL, ap, environ);
  257.                 free(ap);
  258.             }
  259.             goto done;
  260.         }
  261.         case ETXTBSY:
  262.             if (etxtbsy < 3)
  263.                 (void)sleep(++etxtbsy);
  264.             goto retry;
  265.         default:
  266.             goto done;
  267.         }
  268.     }
  269.     if (eacces)
  270.         errno = EACCES;
  271.     else if (!errno)
  272.         errno = ENOENT;
  273.     KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  274. done:    if (path)
  275.         free(path);
  276.     return(-1);
  277. }
  278.